package hc.bre.runner

import hc.bre.cmn.RuleDefinition
import hc.bre.cmn.RuleScriptBuilder

@groovy.transform.CompileStatic
class ScriptLoaderRunner extends RuleRunnerSupportEx{
	String ruleClassScript;

	Closure cachedRule;

	static ScriptLoaderRunner forRule(RuleDefinition ruleDef,RuleScriptBuilder builder=null,String classpath=null) {
		if(builder == null ) {
			builder = ruleDef.scriptBuilderClass().getConstructor().newInstance();
		};

		builder.forRule(ruleDef);

		return new ScriptLoaderRunner
				(ruledir:classpath,
				ruleClassScript:builder.build(),rpath:ruleDef.rpath);
	}

	public Object run(Object namedArgsMap) {
		Map map = namedArgsMap as Map;

		if(map==null)map= [:];

		//cache class
		if(cachedRule == null) {
			Class clazz = buildRuleClass();
			cachedRule = clazz.getField('rule').get(clazz) as Closure;
		}

		//		rule =  rule.clone() as Closure;
		//		rule.delegate = map;
		//		def ret =  rule.call(map) ;
		//		(map as Map).result = ret;
		//		return map;

		map.result = map.with(cachedRule);
		return map;
	}

	public Class buildRuleClass() {
		def codeSource = new GroovyCodeSource(ruleClassScript,
				classFullName()+'.groovy',
				System.getProperty("java.io.tmpdir"));

		GroovyClassLoader classLoader =
				new GroovyClassLoader(Thread.currentThread().getContextClassLoader(),
				configuration(ruledir));

		Class clazz = null;
		try {
			//clazz = classLoader.parseClass(scriptBlock);
			clazz = classLoader.parseClass(codeSource);
		}
		catch(Exception ex) {
			RuleRunnerSupport._log.error("CompilationException when to complile this bellow script.\n{}",ruleClassScript)
			throw ex;
		}
		return clazz
	}
}
